﻿using Data.Entities;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Data.DbContext;
using Repository.Interface;
using Common.Core;
using Common.Extension;
using Data.AggregateRoot;

namespace Repository
{
    /// <summary>
    /// 数据仓储基类
    /// </summary>
    /// <typeparam name="TEntity">实体</typeparam>
    public abstract class RepositoryBase<TEntity> : IRepositoryBase<TEntity> where TEntity : class, IPrimaryKey<Guid>, ISoftDelete

    {
        #region 私有参数
        private readonly DbContext _dbContext = null;
        private readonly DbSet<TEntity> _dbSet = null;
        private bool _isSoft = true;
        #endregion

        #region 构造器
        /// <summary>
        /// 构造器
        /// </summary>
        //protected RepositoryBase(){}

        protected RepositoryBase(DbContext context)
        {
            _dbContext = _dbContext ?? context;
            _dbSet = _dbContext.Set<TEntity>();
        }
        #endregion

        /// <summary>
        /// 设置成物理删除
        /// </summary>
        public void SetPhyDelete()
        {
            _isSoft = false;
        }

        #region 新增
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="entity"></param>
        public virtual async Task CreateAsync(TEntity entity)
        {
            _dbSet.Add(entity);
            await _dbContext.SaveChangesAsync();
        }
        #endregion

        #region 批量新增
        /// <summary>
        /// 批量新增
        /// </summary>
        /// <param name="entitys"></param>
        public virtual async Task CreateAsync(IList<TEntity> entitys)
        {
            if (entitys.HasElement())
            {
                entitys.Each(c =>
                {
                    _dbSet.Add(c);
                });
                await _dbContext.SaveChangesAsync();
            }
        }
        #endregion

        #region 更新数据
        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="entity"></param>
        public virtual async Task UpdateAsync(TEntity entity)
        {
            if (entity != null)
            {
                _dbContext.Entry(entity).State = EntityState.Modified;
                await _dbContext.SaveChangesAsync();
            }
        }

        /// <summary>
        /// 批量更新数据
        /// </summary>
        /// <param name="entityList">实体集合</param>
        public virtual async Task UpdateAsync(IList<TEntity> entityList)
        {
            if (entityList.HasElement())
            {
                foreach (var entity in entityList)
                {
                    _dbContext.Entry(entity).State = EntityState.Modified;
                }
                await _dbContext.SaveChangesAsync();
            }
        }
        #endregion

        #region 删除
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id">主键</param>
        public virtual async Task DeleteAsync(Guid id)
        {
            var entity = await FindAsync(id);
            if (entity == null) return;
            if (_isSoft) entity.IsDel = true;
            else _dbSet.Remove(entity);
            await _dbContext.SaveChangesAsync();
        }
        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="ids">主键集合</param>
        public virtual async Task DeleteAsync(IList<Guid> ids)
        {
            IList<TEntity> entities = await _dbSet.Where(c => !c.IsDel && ids.Contains(c.Id)).ToListAsync();
            if (!entities.HasElement()) return;
            await DeleteAsync(entities);
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <returns></returns>
        public virtual async Task DeleteAsync(IList<TEntity> entities)
        {
            if (!entities.HasElement()) return;
            if (_isSoft)
            {
                entities.Each(c =>
                {
                    c.IsDel = true;
                });
            }
            else
            {
                _dbSet.RemoveRange(entities);
            }
            await _dbContext.SaveChangesAsync();
        }
        #endregion

        #region 通过主键获取数据
        /// <summary>
        /// 通过主键获取数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> FindAsync(Guid id)
        {
            return await _dbSet.FindAsync(id);
        }
        #endregion

        #region 获取集合
        /// <summary>
        /// 获取集合
        /// </summary>
        /// <param name="func">表达式树</param>
        /// <returns></returns>
        public virtual async Task<IList<TEntity>> FindAsync(Expression<Func<TEntity, bool>> func)
        {
            return await _dbSet.Where(c => !c.IsDel).Where(func).ToListAsync();
        }
        #endregion

        #region 获取第一条数据
        /// <summary>
        /// 获取第一条数据
        /// </summary>
        /// <param name="func">表达式树</param>
        /// <returns></returns>
        public virtual async Task<TEntity> FirstAsync(Expression<Func<TEntity, bool>> func)
        {
            return await _dbSet.Where(c => !c.IsDel).FirstOrDefaultAsync(func);
        }
        #endregion

    }
}
